package com.own.business.log.login.persistence.business.service.impl;

import co.elastic.clients.elasticsearch._types.SortOrder;
import co.elastic.clients.elasticsearch._types.query_dsl.BoolQuery;
import co.elastic.clients.elasticsearch._types.query_dsl.MatchQuery;
import co.elastic.clients.elasticsearch._types.query_dsl.TermQuery;
import com.own.business.log.login.persistence.business.service.LogLoginElasticService;
import com.own.business.log.login.persistence.entity.po.LogLogin;
import com.own.business.log.login.persistence.entity.po.LogLoginElasticPo;
import com.own.business.log.login.persistence.entity.query.LogLoginQuery;
import com.own.business.log.login.persistence.entity.vo.LogLoginElasticVo;
import com.own.component.elastic.entity.BaseElasticPo;
import com.own.component.elastic.service.config.ElasticSearchConfig;
import com.own.component.elastic.service.impl.AbstractBaseElasticService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;

/**
 * LogLoginElasticServiceImpl
 *
 * @author chenxueli
 * @date 2023-12-20 10:12:00
 */
@Slf4j
@Service
public class LogLoginElasticServiceImpl extends AbstractBaseElasticService<
        LogLogin,
        LogLoginElasticPo,
        LogLoginElasticVo,
        LogLoginQuery
        > implements LogLoginElasticService {

    @PostConstruct
    private void initIndex() {
        var flag = checkIndex();
        if (flag) {
            return;
        }
        createIndex();
    }

    /**
     * 根据链路id获取日志信息
     *
     * @param traceId 链路id
     * @return 日志信息
     */
    @Override
    public LogLoginElasticVo getByTraceId(String traceId) {
        var config = ElasticSearchConfig.<LogLogin, LogLoginElasticPo, LogLoginElasticVo, LogLoginQuery>builder()
                .queryBuilder(query ->
                        builder ->
                                builder.match(
                                        MatchQuery.of(m -> m.field(LogLoginElasticPo.Fields.traceId).query(traceId))
                                ))
                .sortBuilder(query -> sort -> sort.field(field ->
                        field.field(BaseElasticPo.Fields.gmtCreate).order(SortOrder.Desc)
                ))
                .build();
        return getFirst(new LogLoginQuery(), config);
    }

    /**
     * 根据用户id查询最新的登录日志信息
     *
     * @param userId 用户id
     * @return 最新的登录日志信息
     */
    @Override
    public LogLoginElasticVo getLastLoginTimeByUserId(Long userId) {
        var config = ElasticSearchConfig.<LogLogin, LogLoginElasticPo, LogLoginElasticVo, LogLoginQuery>builder()
                .queryBuilder(query ->
                        builder ->
                                builder.match(
                                        MatchQuery.of(m -> m.field(LogLoginElasticPo.Fields.fkUserId).query(userId))
                                ))
                .sortBuilder(query -> sort -> sort.field(field ->
                        field.field(BaseElasticPo.Fields.gmtCreate).order(SortOrder.Desc)
                ))
                .build();
        return getFirst(new LogLoginQuery(), config);
    }

    /**
     * 获取最近的一次登录日志信息
     *
     * @param account 账号信息
     * @param type    登录方式
     * @param status  登录的状态信息
     * @return 最新的登录日志信息
     */
    @Override
    public LogLoginElasticVo getLastLoginTimeByAccountAndType(String account, String type, Integer status) {
        var config = ElasticSearchConfig.<LogLogin, LogLoginElasticPo, LogLoginElasticVo, LogLoginQuery>builder()
                .queryBuilder(query -> {
                    // 设置关系
                    var bool = BoolQuery.of(b -> {
                        b.must(TermQuery.of(m -> m.field(LogLoginElasticPo.Fields.loginAccount).value(account))._toQuery());
                        b.must(TermQuery.of(m -> m.field(LogLoginElasticPo.Fields.loginType).value(type))._toQuery());
                        b.must(TermQuery.of(m -> m.field(LogLoginElasticPo.Fields.status).value(status))._toQuery());
                        return b;
                    });
                    return builder -> builder.bool(bool);
                })
                .sortBuilder(query -> sort -> sort.field(field ->
                        field.field(BaseElasticPo.Fields.gmtCreate).order(SortOrder.Desc)
                ))
                .build();
        return getFirst(new LogLoginQuery(), config);
    }

    /**
     * 默认的查询配置
     */
    public static final ElasticSearchConfig<
            LogLogin,
            LogLoginElasticPo,
            LogLoginElasticVo,
            LogLoginQuery
            > DEFAULT_CONFIG;

    static {
        DEFAULT_CONFIG = ElasticSearchConfig.<
                        LogLogin,
                        LogLoginElasticPo,
                        LogLoginElasticVo,
                        LogLoginQuery
                        >builder()
                .queryBuilder(query -> {
                    // 设置关系
                    var bool = BoolQuery.of(b -> {
                        if (query.getStatus() != null) {
                            b = b.must(TermQuery.of(m -> m.field(LogLoginElasticPo.Fields.status).value(query.getLoginAccount()))._toQuery());
                        }
                        if (query.getUserId() != null) {
                            b = b.must(TermQuery.of(m -> m.field(LogLoginElasticPo.Fields.fkUserId).value(query.getUserId()))._toQuery());
                        }
                        if (StringUtils.isNotBlank(query.getToken())) {
                            b = b.must(TermQuery.of(m -> m.field(LogLoginElasticPo.Fields.token).value(query.getToken()))._toQuery());
                        }
                        if (query.getStatus() != null) {
                            b = b.must(TermQuery.of(m -> m.field(LogLoginElasticPo.Fields.status).value(query.getStatus()))._toQuery());
                        }
                        if (StringUtils.isNotBlank(query.getUserName())) {
                            b = b.must(MatchQuery.of(m -> m.field(LogLoginElasticPo.Fields.userName).query(query.getUserName()))._toQuery());
                        }
                        if (StringUtils.isNotBlank(query.getClient())) {
                            b = b.must(MatchQuery.of(m -> m.field(LogLoginElasticPo.Fields.client).query(query.getClient()))._toQuery());
                        }
                        if (StringUtils.isNotBlank(query.getIp())) {
                            b = b.must(MatchQuery.of(m -> m.field(LogLoginElasticPo.Fields.ip).query(query.getIp()))._toQuery());
                        }
                        if (StringUtils.isNotBlank(query.getTraceId())) {
                            b = b.must(MatchQuery.of(m -> m.field(LogLoginElasticPo.Fields.traceId).query(query.getTraceId()))._toQuery());
                        }
                        return b;
                    });
                    return builder -> builder.bool(bool);
                })
                .sortBuilder(query -> sort -> sort.field(field ->
                        field.field(BaseElasticPo.Fields.gmtCreate).order(SortOrder.Desc)
                ))
                .build();
    }

    /**
     * 文档名称
     *
     * @return 文档名称
     */
    @Override
    public String index() {
        return "log-login";
    }

}
